package baseFx.log;

import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.filter.AbstractFilter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

public class FxFilter extends AbstractFilter implements FxLogSetting {
    private final List<Level> levelList = new ArrayList<>();
    private final List<String> posList = new ArrayList<>();

    public FxFilter(Level... levels) {
        levelList.addAll(Arrays.asList(levels));
    }

    @Override
    public Result filter(LogEvent event) {
        boolean b = levelList.contains(Level.fromLog4j(event.getLevel()));
        if (b && posList.isEmpty() == false && event.getSource() != null) {
            b = false;
            for (String item : posList) {
                if (item.startsWith("[")) {
                    int i = item.indexOf("]");
                    String lv = item.substring(0, i).replace("[", "");
                    if (event.getLevel().name().equalsIgnoreCase(lv) == false) {
                        continue;
                    }
                    item = item.substring(i + 1);
                }
                String line = "";
                int idx = item.indexOf(":");
                if (idx > 0) {
                    line = item.substring(idx + 1);
                    item = item.substring(0, idx);
                }
                String regex = item.replace(".", "\\.").replace("*", ".*");
                Pattern pat = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
                String value = event.getSource().getClassName() + "." + event.getSource().getMethodName();
                if (pat.matcher(value).find() == false) {
                    continue;
                }
                if (line.isEmpty() == false) {
                    String[] items = line.split("-");
                    int num = event.getSource().getLineNumber();
                    int n1 = Integer.parseInt(items[0]);
                    if (items.length == 2) {
                        int n2 = Integer.parseInt(items[1]);
                        if (n1 > num || n2 < num) {
                            continue;
                        }
                    } else if (n1 != num) {
                        continue;
                    }
                }
                b = true;
                break;
            }
        }
        return b ? Result.ACCEPT : Result.DENY;
    }

    @Override
    public List<Level> getLevels() {
        return levelList;
    }

    @Override
    public List<String> getLocation() {
        return posList;
    }
}
